/*
 * Created on 2004-12-20
 */
package dk.aiszone.lang.autosource.generatorobjects;

import java.util.Collections;
import java.util.Set;

import dk.aiszone.lang.autosource.generatorobjects.interfaces.GeneratorObject;

/**
 * The <code>GenericClass</code> class extends the <code>Class</code> object inorder to provide<br>
 * generics declarations within <code>Classes</code>.<br>
 * <br>
 * The <code>GenericClass</code> allows declarations such as &quot;TestMap&lt;String, Set&lt;? extends Object&gt;&gt;&quot;
 * 
 * @author <a href="mailto:ais@mail.dk">Ais</a>
 * @since 1.0
 * @version 1.0
 * 
 * @see Class
 */
public class GenericClass extends GeneratorObject implements Cloneable {

    private String identifier;
    private Operator operator;
    private Class type;

    /**
     * Constructor for the <code>GenericClass</code> class.<br>
     * This constructor is used when adding a simple generic like <code>Object</code> with out the <code>extends</code> part.
     * 
     * @param type
     *            The package to represent.<br>
     *            The supplied package is expected to the the class name including the complete package path.
     */
    public GenericClass(Class type) {
        this.operator = Operator.NONE;
        this.identifier = null;
        this.type = type;
    }

    /**
     * Constructor used for creating a <code>GenericClass</code> only containing an identifier.
     * 
     * @param identifier
     *            The identifier of the <code>GenericClass</code>.
     */
    public GenericClass(String identifier) {
        this(identifier, null, null);
    }

    /**
     * Constructor for the <code>GenericClass</code> class.<br>
     * ie.: &lt;T extends Object&gt;
     * 
     * @param identifier
     *            The identifier to use in the declaration.
     * @param operator
     *            <code>Operator</code> indicating whether the declaration is declaraed as <b>extends</b> or <b>super</b>.
     * @param type
     *            The package to represent.<br>
     *            The supplied package is expected to the the class name including the complete package path.
     */
    public GenericClass(String identifier, Operator operator, Class type) {
        this.operator = operator;
        this.identifier = identifier;
        this.type = type;
    }

    /**
     * Private constructor used for cloning.
     */
    private GenericClass() {
    // Do nothing
    }

    @Override
    public Object clone() {
        GenericClass clone = new GenericClass();
        clone.identifier = this.identifier;
        clone.operator = this.operator;
        clone.type = this.type;
        return clone;
    }

    /**
     * Retrieve the identifier of the <code>GenericClass</code>.
     * 
     * @return The identifier to use in the declaration.
     */
    public String getIdentifier() {
        return identifier;
    }

    /**
     * Retrieve whether the declaration is declaraed as <b>extends</b> or <b>super</b> or none.
     * 
     * @return <code>Operator</code> indicating whether the declaration is declaraed as <b>extends</b> or <b>super</b>.
     */
    public Operator getOperator() {
        return operator;
    }

    /**
     * Retrieve the type being extended.
     * 
     * @return <code>Class</code> representation of the extended class.
     */
    public Class getType() {
        return type;
    }

    /**
     * Retrieve whether the <code>GenericClass</code> requires imports to be added to the containing body.
     * 
     * @return <code>true</code> if imports are required - otherwise <code>false</code>.
     */
    public boolean requiresImport() {
        if (type != null) {
            return type.requiresImport();
        }
        return false;
    }

    /**
     * Retrieve the <code>Imports</code> needed by the <code>GenericClass</code>.<br>
     * This method returns the same as <code>getType().toImports()</code>.
     * 
     * @return <code>Set</code> of needed <code>Imports</code>.
     */
    public Set<Import> toImports() {
        if (type != null) {
            return type.toImports();
        }
        return Collections.emptySet();
    }

    /**
     * Enum containing the supported operators of the <code>GenericClass</code>.
     */
    public static enum Operator {
        /** The <code>extends</code> operator */
        EXTENDS,
        /** No operator */
        NONE,
        /** The <code>super</code> operator */
        SUPER;
    }
}